<?php

namespace app\miniprograms\controller;

use controller\BasicAdmin;
use service\DataService;
use service\NodeService;
use service\ToolsService;
use think\App;;
use think\Db;
use app\common\model\Enum;

use app\common\library\excel\Office;
use think\facade\Log;
use app\api\model\HttpMachine;

/**
 * 订单管理
 * @package app\admin\controller
 * @author liuda <1576283429@qq.com>
 */
class Order extends BasicAdmin
{
    public $table = 'order';
    /**
     * 订单管理列表
     */
    public function index(){
        $this->title = '订单管理';
        $where = ' 1=1 ';
        $area = $this->request->get('area');
        $pay_status = $this->request->get('pay_status');
        $date = $this->request->get('date');
        $card_no = $this->request->get('card_no');
        $machine_no = $this->request->get('machine_no');
        $code = $this->request->get('code');

        $excel = $this->request->get('excel');

        $session = $this->request->session();
        $user = $session['user'];  //$user['is_admin']  1为管理员  其余是供应商
        $wherearea = ' ';
        
        if( $user['is_admin'] !=1 ){
           $ids= $user['area'];
           if(empty($ids)){
             $ids="0";
           }
           $where .=" AND A.area_id in ( $ids ) ";
           $wherearea =" AND id in ( $ids ) ";
          
        }
 
        if(is_numeric($area)){
            $where .= " AND A.area_id = $area ";
        }
       
        if(is_numeric($pay_status)){
            $where .= " AND A.pay_status = $pay_status ";
        }
       if(!empty($date)){
           list($start, $end) = explode(' - ', $date);
           $start = $start." 00:00:00";
           $end = $end." 23:59:59";
           $where .=" AND A.create_at >= '$start'  AND A.create_at <= '$end' ";
       }

        if(!empty($card_no)){
           $where .= " AND A.card_no = '$card_no' ";
        }

        if(!empty($code)){
            $user = Db::table('user')->where("code",$code)->find();
            $code=0;
            if($user){
                $code=$user["id"];
            }
            $where .= " AND A.user_id = $code ";
         }

        if(!empty($machine_no)){
            $where .= " AND A.machine_no = '$machine_no' ";
         }
      

        $areas = Db::table('area')->field('id,area_name')->where("is_deleted = 0 $wherearea ")->select(); //获取地区
        $this->assign('areas', $areas);

        $orderPaystatus = ['已付款','付款失败','未付款'];
        $this->assign('orderPaystatus', $orderPaystatus);

        $this->assign('wash_type_array', Enum::wash_type_array);

        $list =  Db::table('order')->alias('A')->join('machine M','A.machine_no = M.machine_no','LEFT')->join('area E','A.area_id = E.id','LEFT')->field('A.id,A.card_no, A.machine_no,A.amount, A.pay_status,A.order_no ,A.update_at,A.wash_type,E.area_name,A.isback,M.dormitory_num')->where($where)->order('A.id desc');

        if($excel=="1"){

            $list =$list->select();
            foreach ($list as &$row){
                $tname = array_search($row["pay_status"],Enum::PAY_array);
                if(empty($tname)){
                    $tname="";
                }
                $row["tname"] =$tname;
                $row["amount"] =$row["amount"]/100;
            }
            $fileName = '订单明细'.date('_YmdHis');
            $head = ['机器编码','机器地区','具体位置','卡编码','订单金额(元)','订单状态','订单编号','订单时间'];
            $keys = ['machine_no','area_name','dormitory_num','card_no','amount','tname','order_no','update_at'];   
            $excel = new Office(); 
            $excel->outExcel($fileName, $list, $head, $keys);
        }else{
            return parent::_list($list);
        }
    }


    /**
     * 转码，防止导出乱码
     * @param $data
     * @return array|string
     */
    private static function self_mb_convert_encoding($data){
        if(is_array($data)){
            foreach ($data as $k => $v){
                $data[$k] = mb_convert_encoding($v,"GBK", "UTF-8");
            }
        }
        if(is_string($data)){
            $data = mb_convert_encoding($data,"GBK", "UTF-8");
        }
        return $data;
    }


    public function report(){
        $this->title = '订单统计';
        $where = ' 1 ';
        $area = $this->request->get('area');
        $pay_status = $this->request->get('pay_status');
        $date = $this->request->get('date');
        $machine_no = $this->request->get('machine_no');

        $session = $this->request->session();
        $user = $session['user'];  //$user['is_admin']  1为管理员  其余是供应商
        $wherearea = ' ';
        if( $user['is_admin'] !=1 ){
            $ids= $user['area'];
            if(empty($ids)){
                $ids="0";
              }
           $where .=" AND R.area_id in ( $ids ) ";
           $wherearea =" AND id in ( $ids ) ";
        }

        if(is_numeric($area)){
            $where .= " AND R.area_id = $area ";
        }

        if(is_numeric($pay_status)){
            $where .= " AND R.pay_status = $pay_status ";
        }
        if(!empty($date)){
            list($start, $end) = explode(' - ', $date);
            $start = $start." 00:00:00";
            $end = $end." 23:59:59";
            $where .=" AND R.create_at >= '$start'  AND R.create_at <= '$end' ";
        }else{
            $firstDay = date('Y-m-01', strtotime(date("Y-m-d")));
            $lastDay =  date('Y-m-d', strtotime("$firstDay +1 month -1 day"));
            $this->assign('date', $firstDay." - ".$lastDay);

            $start = $firstDay." 00:00:00";
            $end = $lastDay." 23:59:59";
            $where .=" AND R.create_at >= '$start'  AND R.create_at <= '$end' ";
        }

        if(!empty($machine_no)){
            $where .= " AND R.machine_no = '$machine_no' ";
        }

        $areas = Db::table('area')->field('id,area_name')->where("is_deleted = 0 $wherearea ")->select(); //获取地区
        $this->assign('areas', $areas);

        $orderPaystatus = ['已付款','付款失败','未付款'];
        $this->assign('orderPaystatus', $orderPaystatus);

        

        $sql = " SELECT sum(case when R.pay_status = 0 then R.amount else 0 end) as 'success',sum(case when R.pay_status = 2 then R.amount else 0 end) as 'noPay',sum(case when R.pay_status = 1 then R.amount else 0 end) as 'faild' from `order` as  R left join machine as M on R.machine_no = M.machine_no  WHERE {$where} ";
         
        $list = Db::query($sql);
        if(!empty($list[0])){
            $this->assign('list', $list[0]);
        }

        return $this->fetch('order/report');
    }


    

    /*
    * 编辑
    */
    public function edit()
    {
        return $this->_form_self($this->table, 'form');
    }


    public function _form_self($dbQuery = null, $tplFile = '', $pkField = '', $where = [], $extendData = [])
    {
        $db = is_null($dbQuery) ? Db::name($this->table) : (is_string($dbQuery) ? Db::name($dbQuery) : $dbQuery);
        $pk = empty($pkField) ? ($db->getPk() ? $db->getPk() : 'id') : $pkField;
        $pkValue = $this->request->request($pk, isset($where[$pk]) ? $where[$pk] : (isset($extendData[$pk]) ? $extendData[$pk] : null));
        // 非POST请求, 获取数据并显示表单页面
        if (!$this->request->isPost()) {
            $vo = ($pkValue !== null) ? array_merge((array)$db->where($pk, $pkValue)->where($where)->find(), $extendData) : $extendData;
            empty($this->title) || $this->assign('title', $this->title);
            return $this->fetch($tplFile, ['vo' => $vo]);
        }
        // POST请求, 数据自动存库
        $data = array_merge($this->request->post(), $extendData);
        //判断是否已经退款了. 已退款不能再次退款
       

        $time =date('Y-m-d H:i:s',time());
         
        $map=[
            ['id', '=', $data['id']]
        ];
        $order=Db::table('order')->where($map)->find();
        if(empty($order)){
            $this->error('订单丢失或已支付!');
            return false;
        }

        if($order["isback"]==1){
            $this->error('单据已退款, 不能再次退款!');
            return false;
        }

        //已退款
        $user = Db::table('user')->where("id",$order['user_id'])->find();
        if(!$user){
            $this->error('user is empty!');
            return false;
        }

        $back_remark = $data['back_remark'];

        //判断是那种支付 
        $washcode = strtolower(substr($order["order_no"], 0, 4));
        if($washcode =="scan"){
            //微信退款
            $map=[
                ['order_id', '=', $order['id']]
            ];
            $refund = Db::table('refund')->where($map)->find();
            if(!$refund){

                $time =date('Y-m-d H:i:s',time());
                $refund=[
                    'user_id' => $user['id'],
                    'status' => 2,
                    'create_at' => $time,
                    'update_at' => $time,
                    'amount' => $order["amount"],
                    'order_id' => $order["id"]
                ];
                $id=Db::table('refund')->insertGetId($refund);
                $refund["id"] = $id;
            }

            $re_openid = $user['open_id'];
            $total_amount = $refund['amount'];
            $desc='e共享不愁洗衣退款到账';
            $check_name='';

            //企业付款到微信零钱，PHP接口调用方法   key=
            $APPID="wxdedae9ac8da366ad"; // 商户账号appid
            $MCHID="1523166321";  // 商户号
            $SECRECT_KEY="537f141c6f89d1cf622e2dc7f017b207"; //支付密钥签名

            $data=array(
                'mch_appid'=>$APPID,//商户账号appid
                'mchid'=> $MCHID,//商户号
                'nonce_str'=>$this->createNoncestr(),//随机字符串
                'partner_trade_no'=> date('YmdHis').rand(1000, 9999),//商户订单号
                'openid'=> $re_openid,//用户openid
                'check_name'=>'NO_CHECK',//校验用户姓名选项,
                're_user_name'=> $check_name,//收款用户姓名
                'amount'=>$total_amount,//金额
                'desc'=> $desc,//企业付款描述信息
                'spbill_create_ip'=> $this->request->ip(),//Ip地址
            );

            

            //生成签名算法
            $secrect_key=$SECRECT_KEY;///这个就是个API密码。MD5 32位。
            $data=array_filter($data);
            ksort($data);
            $str='';
            foreach($data as $k=>$v) {
            $str.=$k.'='.$v.'&';
            }
            $str.='key='.$secrect_key;
            $data['sign']=md5($str);
            //生成签名算法
            $xml=$this->arraytoxml($data);
            $url='https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers'; //调用接口
            $res=$this->curl_post_ssl($url,$xml);
            $responseObj=$this->xmltoarray($res);

            $rescode= $responseObj["return_code"];
            if($rescode =="SUCCESS"){

                $result_code= $responseObj["result_code"];
                if($result_code =="FAIL"){
                    $err_code_des = $responseObj["err_code_des"];
                    $err_code = $responseObj["err_code"];
                    Log::record(json_encode($responseObj),'emergency');

                    $this->error('退款失败-2!');
                    return false;

                }else{
                    $trade_no = $responseObj["partner_trade_no"];
                    $payment_no = $responseObj["payment_no"];
        
                    $session = $this->request->session();
                    $user = $session['user']; 
                    $time =date('Y-m-d H:i:s',time());

                    Db::table('order')->where('id',$order['id'])->update([ 'back_user_id'=> session('user.id'), 'update_at' => $time,'isback'=>1,'back_remark'=>$back_remark ]);
                    
                    Db::table('refund')->where('id',$refund['id'])->update([ 'status'=> 0, 'update_at' => $time, 'update_at' => $time,'update_user_id'=>$user["id"],'payment_no'=>$payment_no]);
                }
            }else{
                $this->error('退款失败-1!');
                return false;
            }
        }else if($washcode =="card"){
            //追加充值记录 //账户流水
            $no_cz = Enum::orderNo(Enum::order_type_tdcz);
            $data_cz=[
                'user_id' => $order['user_id'],
                'open_id' => $order['open_id'],
                'union_id' => $order['union_id'],
                'type' => Enum::b_type_tdcz,
                'trade_no' =>$order['order_no'],//记录退订订单的单号
                'card_no' => "",
                'order_no' => $no_cz,
                'apsid' => "",//这个没有什么意义了
                'pay_status' => Enum::PAY_SUCESS,
                'create_at' => $time,
                'update_at' => $time,
                'czamount' => $order['amount'],
                'amount' => $order['amount'],
                'gift' => 0
            ];
            $book_cz=[
                'user_id' => $order['user_id'],
                'b_type' => Enum::b_type_tdcz,
                'b_id' => 0,
                'b_no' => $no_cz,
                'create_at' => $time,
                'old_amount' =>$user['amount'],
                'var_amount' =>$order['amount'] ,
                'amount' => $user['amount'] + $order['amount']
            ];

            Db::startTrans();
            try {
                //先充值
                $charge_id=Db::table('charge')->insertGetId($data_cz);
                $book_cz['b_id'] = $charge_id;
                Db::table('daybook')->strict(false)->insert($book_cz);

                Db::table('order')->where('id',$order['id'])->update([ 'back_user_id'=> session('user.id'), 'update_at' => $time,'isback'=>1,'back_remark'=>$data['back_remark'] ]);

                //用户的钱变化
                $c = Db::table('user')->where('id',$user['id'])->setInc('amount',$order['amount']);
                // 提交事务
                Db::commit();
            } catch (\Exception $e) {
                // 回滚事务
                Db::rollback();
                $this->error('数据更新异常!');
                return false;
            }
        }else{
            $this->error('该单据不能退款!');
            return false;
        }
        $this->success('恭喜, 数据保存成功!', '');
    }

    public  function getrow($val){
		if(!empty($val)){
			return $val;
		}
		return '';
    }
    

    public function xiyici()
    {
        $id = $this->request->get('id');
        $map=[
            ['id', '=', $id]
        ];
        $order=Db::table('order')->where($map)->find();
        if(empty($order)){
            $this->error('订单丢失或已支付!');
            return false;
        }
        $machineNo = $order["machine_no"];
        $action = $order["wash_type"];

        $re = HttpMachine::GetMachineWorkStatus($machineNo);
        if($re == ""){
            return $this->error("洗衣机呼叫失败");
            exit();
        }
        if($re != "1"){
            return $this->error("洗衣机正在工作中或呼叫失败");
            exit();
        }

        $re=HttpMachine::SendWashCammand($machineNo,$action);

        if($re==1){
            $this->success("命令发送成功", '');
        }else{
            $this->success("命令发送次失败", '');
        }
        
    }



      /**
 * [xmltoarray xml格式转换为数组]
 * @param [type] $xml [xml]
 * @return [type]  [xml 转化为array]
 */
public function xmltoarray($xml) { 
    //禁止引用外部xml实体 
    libxml_disable_entity_loader(true); 
    $xmlstring = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA); 
    $val = json_decode(json_encode($xmlstring),true); 
    return $val;
   }
  
   /**
   * [arraytoxml 将数组转换成xml格式（简单方法）:]
   * @param [type] $data [数组]
   * @return [type]  [array 转 xml]
   */
   function arraytoxml($data){
    $str='<xml>';
    foreach($data as $k=>$v) {
     $str.='<'.$k.'>'.$v.'</'.$k.'>';
    }
    $str.='</xml>';
    return $str;
   }
  
   /**
   * [createNoncestr 生成随机字符串]
   * @param integer $length [长度]
   * @return [type]   [字母大小写加数字]
   */
  public  function createNoncestr($length =32){
    $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789"; 
    $str ="";
  
    for($i=0;$i<$length;$i++){ 
     $str.= substr($chars, mt_rand(0, strlen($chars)-1), 1); 
    } 
    return $str;
   }
  
   /**
   * [curl_post_ssl 发送curl_post数据]
   * @param [type] $url  [发送地址]
   * @param [type] $xmldata [发送文件格式]
   * @param [type] $second [设置执行最长秒数]
   * @param [type] $aHeader [设置头部]
   * @return [type]   [description]
   */
  public  function curl_post_ssl($url, $xmldata, $second = 30, $aHeader = array()){
    $isdir = $_SERVER['DOCUMENT_ROOT']."/cert/";//证书位置;绝对路径

    $ch = curl_init();//初始化curl
  
    curl_setopt($ch, CURLOPT_TIMEOUT, $second);//设置执行最长秒数
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//要求结果为字符串且输出到屏幕上
    curl_setopt($ch, CURLOPT_URL, $url);//抓取指定网页
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);// 终止从服务端进行验证
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);//
    curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');//证书类型
    curl_setopt($ch, CURLOPT_SSLCERT, $isdir . 'apiclient_cert.pem');//证书位置
    curl_setopt($ch, CURLOPT_SSLKEYTYPE, 'PEM');//CURLOPT_SSLKEY中规定的私钥的加密类型
    curl_setopt($ch, CURLOPT_SSLKEY, $isdir . 'apiclient_key.pem');//证书位置
    //curl_setopt($ch, CURLOPT_CAINFO, 'PEM');
    //curl_setopt($ch, CURLOPT_CAINFO, $isdir . 'rootca.pem');
    if (count($aHeader) >= 1) {
     curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);//设置头部
    }
    curl_setopt($ch, CURLOPT_POST, 1);//post提交方式
    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmldata);//全部数据使用HTTP协议中的"POST"操作来发送
  
    $data = curl_exec($ch);//执行回话
    if ($data) {
     curl_close($ch);
     return $data;
    } else {
     $error = curl_errno($ch);
     Log::record("curl_post_ssl call faild, errorCode:$error",'emergency');
     curl_close($ch);
     return false;
    }
   }

}